package com.ikkong.biz.service.impl;

import com.google.common.collect.BiMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ikkong.biz.BizCst;
import com.ikkong.biz.excel.ExcelStudentVerifyHandlerImpl;
import com.ikkong.biz.excel.StudentDataHandler;
import com.ikkong.biz.excel.StudentOfMode;
import com.ikkong.biz.excel.TeacherOfMode;
import com.ikkong.biz.model.*;
import com.ikkong.biz.service.AsyncResultService;
import com.ikkong.biz.service.ClassesService;
import com.ikkong.common.vo.User;
import com.ikkong.core.base.service.impl.BaseService;
import com.ikkong.biz.service.StudentService;
import com.ikkong.core.constant.ConstCache;
import com.ikkong.core.dao.Blade;
import com.ikkong.core.dao.Db;
import com.ikkong.core.exception.BizException;
import com.ikkong.core.jfinal.ext.kit.JStrKit;
import com.ikkong.core.jfinal.ext.kit.JsonKit;
import com.ikkong.core.jfinal.ext.shiro.ShiroKit;
import com.ikkong.core.toolbox.Conver;
import com.ikkong.core.toolbox.ExcelStatistic;
import com.ikkong.core.toolbox.Record;
import com.ikkong.system.model.Dept;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.PathKit;
import com.jfinal.kit.PropKit;
import com.jfinal.kit.StrKit;
import com.jfinal.plugin.ehcache.CacheKit;

import org.apache.commons.io.IOUtils;
import org.beetl.sql.core.SQLReady;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.entity.result.ExcelImportResult;
import org.jeecgframework.poi.exception.excel.ExcelImportException;
import org.jeecgframework.poi.util.PoiPublicUtil;

import java.io.File;
import java.io.FileOutputStream;
import java.util.BitSet;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Generated by Blade.
 * 2016-11-17 15:53:59
 */
public class StudentServiceImpl extends BaseService<Student> implements StudentService{
    private static final String filePath = "excel"+ File.separator+"student"+File.separator+"student_import.xlsx";
    private ClassesService service = new ClassesServiceImpl();
    private AsyncResultService asyncResultService = new AsyncResultServiceImpl();

    @Override
    public String doImport(File file) throws BizException {
        boolean flag = preValid();
        if (flag){
            throw new BizException("正在导入中，请稍后再试!");
        }

        PropKit.use("config.properties");
        String realpath = PathKit.getWebRootPath()+File.separator+ filePath;
        try (FileOutputStream fos= new FileOutputStream(realpath)){
            ImportParams params = new ImportParams();
            params.setNeedVerfiy(true);
            params.setVerifyHanlder(new ExcelStudentVerifyHandlerImpl());
            ExcelImportResult<StudentOfMode> result = ExcelImportUtil.importExcelVerify(
            		file,
                    StudentOfMode.class, params);
            result.getWorkbook().write(fos);

            //拼装学生跟家长model
            int stuSize = deal(result);

            //插入同步结果数据，导入完成
            asyncResultService.writeResult(AsyncResultService.ASYNC_TYPE.STU_IMPORT,AsyncResultService.SUCCESS,"学生与家长导入",null);
            String reson = ExcelStatistic.statistic(result.getList().size(),stuSize,filePath);
            
            return reson;
        } catch (Exception e) {
			asyncResultService.writeResult(AsyncResultService.ASYNC_TYPE.STU_IMPORT,AsyncResultService.FAILD,"学生与家长导入",null);

            if (e instanceof ExcelImportException){
                throw new BizException(e.getMessage(),e);
            }
            throw new BizException("导入失败",e);
        }finally {
            file.delete();
        }
    }

    private boolean preValid() {
        AsyncResult r = Blade.create(AsyncResult.class).findFirst("select * from tb_async_result where type = #{type}", Record.create().set("type",AsyncResultService.ASYNC_TYPE.STU_IMPORT.name()));
        return  (r.getStatus().intValue() == AsyncResultService.RUNNING);
    }

    private void doInsert(List<Student> stus , List<Parent> parents, List<AsyncWeixin> asyncs){
        new Thread(new Runnable() {
            @Override
            public void run() {
                Blade.dao().insertBatch(Student.class,stus);
                Blade.dao().insertBatch(Parent.class,parents);
            }
        }).start();

        /*ExecutorService exe = Executors.newFixedThreadPool(2);
        exe.execute(new Runnable() {
            @Override
            public void run() {
                Blade.dao().insertBatch(Student.class,stus);
            }
        });

        exe.execute(new Runnable() {
            @Override
            public void run() {
                Blade.dao().insertBatch(Parent.class,parents);
            }
        });

        System.out.println("已经开启所有的子线程");
        exe.shutdown();

        while(true){
            if(exe.isTerminated()){
                System.out.println("所有的子线程都结束了！");
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }*/

    }

    private int deal(ExcelImportResult<StudentOfMode> result){

        List<Student> list = Lists.newArrayList();
        List<Parent> ps = Lists.newArrayList();
        List<AsyncWeixin> asyncs = Lists.newArrayList();

        BiMap<String,Integer> maps = CacheKit.get(ConstCache.SYS_CACHE,"classes_names");
        if (null == maps){
            maps = service.getClassesNames();
        }

        for (StudentOfMode sm: result.getList()
                ) {
            if (JStrKit.isBlank(sm.getErrorMsg())){
                Integer classid = maps.get(sm.getClass_name());
                Classes c = service.findById(classid);
                sm.setCtime(new Date());
                sm.setVersion(0);
                sm.setClass_id(classid);
                sm.setDept_id(c.getStu_dept_id());
                list.add(sm);                


                if (JStrKit.notBlank(sm.getFatherName())){

                    Parent fp = new Parent();
                    fp.setCtime(new Date());
                    fp.setVersion(0);
                    fp.setClass_id(classid);
                    fp.setStu_mobile(sm.getMobile());
                    fp.setStu_name(sm.getName());
                    fp.setName(sm.getFatherName());
                    fp.setDept_id(c.getParent_dept_id());
                    fp.setMobile(sm.getFatherMobile());
                    fp.setPosition(BizCst.FATHER);
                    ps.add(fp);

                }

                if (JStrKit.notBlank(sm.getMotherName())) {

                    Parent fm = new Parent();
                    fm.setCtime(new Date());
                    fm.setVersion(0);
                    fm.setStu_mobile(sm.getMobile());
                    fm.setClass_id(classid);
                    fm.setDept_id(c.getParent_dept_id());
                    fm.setStu_name(sm.getName());
                    fm.setName(sm.getMotherName());
                    fm.setMobile(sm.getMotherMobile());
                    fm.setPosition(BizCst.MOTHER);
                    ps.add(fm);
                    
                }

                if (JStrKit.notBlank(sm.getOtherName())) {

                    Parent fo = new Parent();
                    fo.setCtime(new Date());
                    fo.setVersion(0);
                    fo.setStu_mobile(sm.getMobile());
                    fo.setClass_id(classid);
                    fo.setDept_id(c.getParent_dept_id());
                    fo.setStu_name(sm.getName());
                    fo.setName(sm.getOtherName());
                    fo.setMobile(sm.getOtherMobile());
                    fo.setPosition(BizCst.OTHER);
                    ps.add(fo);                    

                }


            }
        }

        //TODO 异步插入学生，家长数据到表,到时注释删除表数据这两条
//        Blade.dao().executeUpdate(new SQLReady("truncate table tb_student"));
//        Blade.dao().executeUpdate(new SQLReady("truncate table tb_parent"));
        doInsert(list,ps,asyncs);

        return list.size();
    }
}
